package com.zhouheng.springbootmultithreading.module.producerconsumerissues.service.impl;

import com.zhouheng.springbootmultithreading.module.producerconsumerissues.service.Storage;

import java.util.LinkedList;

/**
 * 仓库，生产者与消费者协同的缓冲区
 *
 * @author 周恒
 * @date 20190107 17:36:23
 * @since v1.0
 */
public class WaitNotifySynchronizedStorageImpl implements Storage {

    public WaitNotifySynchronizedStorageImpl(int MAX_SIZE) {
        this.MAX_SIZE = MAX_SIZE;
    }

    /**
     * MAX_SIZE 仓库最大存储量
     */
    private int MAX_SIZE;

    /**
     * list 仓库存储的载体（LinkedList增删比较快）
     */
    private LinkedList<Object> list = new LinkedList<>();

    /**
     * 生产产品
     *
     * @param producer 描述此参数
     * @author 周恒
     * @date 20190107 17:41:46
     * @since v1.0
     */
    @Override
    public void produce(String producer) {
        // 实例锁，类锁，对象锁
//        synchronized (this) {
//        synchronized (WaitNotifySynchronizedStorageImpl.class) {
        synchronized (list) {
            // 如果仓库已满
            while (MAX_SIZE == list.size()) {
                System.out.println("仓库已满，【"+producer+"】： 暂时不能执行生产任务!");
                try {
                    // 由于条件不满足，生产阻塞，会释放锁（别的线程调用notifyAll，才会回到就绪状态，不一定是马上执行）
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 生产产品
            list.add(new Object());
            System.out.println("【"+producer+"】：生产了一个产品\t【现仓储量为】:" + list.size());
            list.notifyAll();
        }
    }

    /**
     * 消费产品
     *
     * @param consumer 描述此参数
     * @author 周恒
     * @date 20190107 17:44:43
     * @since v1.0
     */
    @Override
    public void consume(String consumer) {
        synchronized (list) {
            //如果仓库存储量不足
            while (0 == list.size()) {
                System.out.println("仓库已空，【"+consumer+"】： 暂时不能执行消费任务!");
                try {
                    // 由于条件不满足，消费阻塞，会释放锁
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            list.remove();
            System.out.println("【"+consumer+"】：消费了一个产品\t【现仓储量为】:" + list.size());
            list.notifyAll();
        }
    }


}
